import json
from enum import Enum

from pymysql.cursors import DictCursor, Cursor

from db_pool import SF_DB

batch_size = 1000


class WarehouseType(Enum):
    ZB = '1'  # 栈板
    JX = '2'  # 件箱


class PackType(Enum):
    ZB = '1'  # 栈板
    JX = '2'  # 件箱
    ZZX = '3'  # 自制箱


class PredictionData(object):
    id: str = None
    date: str = None
    group: str = None
    packageType: str = None
    totalNum: str = None
    type: str = None
    inOutType: str = None
    warehouseType: str = None

    def __init__(self, **kwargs):
        field_map = {
            'id': 'id',
            'work_time': 'date',
            'supplier': 'group',
            'pack_type': 'packageType',
            'quantity': 'totalNum',
            'in_out_type': 'inOutType',
            'sku': 'type',
            'warehouse_type': 'warehouseType'
        }
        for key in kwargs:
            if hasattr(self, field_map[key]):
                setattr(self, field_map[key], kwargs[key])

    def __repr__(self):
        return json.dumps(self.to_dict(), indent=4)

    def to_dict(self):

        return {'id': self.id, 'date': self.date, 'group': self.group, 'packageType': self.packageType,
                'totalNum': self.totalNum, 'type': self.type, 'inOutType': self.inOutType,
                'warehouseType': self.warehouseType}


def get_last_days_data(days: int) -> list[PredictionData] | None:
    """
    查询过去days天的数据
    :param days: 天数
    """
    db = SF_DB()
    with db.get_pool().get_connection() as conn:
        cursor = conn.cursor(cursor=DictCursor)
        sql = ("SELECT id ,DATE_FORMAT(work_time,'%%Y-%%m-%%d') AS work_time,"
               "supplier,CAST(pack_type AS CHAR) AS pack_type,"
               "CAST(in_out_type AS CHAR) AS in_out_type,CAST(quantity AS CHAR) AS quantity,sku,warehouse_type "
               "FROM wops_sku_frequency "
               "WHERE work_time BETWEEN DATE_FORMAT(DATE_SUB(NOW(), INTERVAL %s DAY), '%%Y-%%m-%%d') AND DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -1 DAY), '%%Y-%%m-%%d')")
        db_data = cursor.db_query(sql, (days,))
        prediction_data_list = [PredictionData(**row) for row in db_data]
    return prediction_data_list


class ForecastConfig(object):
    # 是否启用计划数据 示例: true
    consider_plan: str = False
    # 考虑数据范围 示例: 60
    data_range: str = 60
    # 最大预测天数 示例: 3
    forecast_day: str = 3

    @property
    def fix_consider_plan(self) -> bool:
        """
        算法 False -> "False"
        """
        return self.consider_plan and self.consider_plan.upper() == 'TRUE'

    @property
    def fix_consider_plan_sb(self) -> str:
        return "True" if self.fix_consider_plan else "False"

    @property
    def fix_data_range(self) -> int:
        return int(self.data_range)

    @property
    def fix_forecast_day(self) -> int:
        return int(self.forecast_day)

    def __str__(self):
        return f'ForecastConfig(consider_plan: {self.fix_consider_plan}, data_range: {self.fix_data_range}, forecast_day: {self.fix_forecast_day})'


def get_forecast_config() -> ForecastConfig:
    with SF_DB().get_pool().get_connection() as conn:
        cursor = conn.cursor(cursor=DictCursor)
        data_list = cursor.db_query(
            'SELECT code, value FROM wops_parameter_config_dtl WHERE parameter_configgroup_code = %s',
            ("forecast_config",))
        fc = ForecastConfig()
        for d in data_list:
            setattr(fc, d['code'], d['value'])
    return fc


class DeliverPlan(object):
    type: str = None
    totalNum: int = None
    inOutType: int = None
    factory_type: int = None
    date: str = None

    def __init__(self, **kwargs):
        for k in kwargs:
            if hasattr(self, k):
                setattr(self, k, kwargs[k])

    @property
    def packageType(self) -> str:
        return PackType.JX.value if self.factory_type == 1 else PackType.ZZX.value


def get_deliver_plan(days: int, history: bool) -> list[DeliverPlan]:
    """
    :param days: 时长(天)
    :param history: True->历史数据，False->未来数据
    """
    with SF_DB().get_pool().get_connection() as conn:
        cursor: Cursor = conn.cursor(cursor=DictCursor)
        base_sql = '''
                    SELECT p.sku AS type, p.quantity as totalNum, p.factory_type, DATE_FORMAT(p.work_time,'%%Y-%%m-%%d') AS date, pv.receive_deliver_type as inOutType
                    FROM wops_future_receive_deliver_plan p 
                    LEFT JOIN wops_future_receive_deliver_plan_version pv ON pv.id = wops_future_receive_deliver_plan_versionid
                    WHERE pv.receive_deliver_type IS NOT NULL
                    '''
        if history:
            data_list = cursor.db_query(
                base_sql + ' AND p.work_time BETWEEN DATE_FORMAT(DATE_ADD(NOW(), INTERVAL %s DAY), "%%Y-%%m-%%d") AND DATE_FORMAT(DATE_ADD(NOW(), INTERVAL -1 DAY), "%%Y-%%m-%%d") ;',
                args=(-days,))
        else:
            data_list = cursor.db_query(
                base_sql + ' AND p.work_time BETWEEN DATE_FORMAT(NOW(), "%%Y-%%m-%%d") AND DATE_FORMAT(DATE_ADD(NOW(), INTERVAL %s DAY), "%%Y-%%m-%%d") ;',
                args=(days,))
        result = []
        for data in data_list:
            result.append(DeliverPlan(**data))
        return result


if __name__ == '__main__':
    fc = get_forecast_config()
    print(fc)
    data_list = get_last_days_data(10)
    h_list = get_deliver_plan(300, history=True)
    f_list = get_deliver_plan(300, history=False)
    x = 3
    pass
